package utils

import (
	"crypto/tls"
	"crypto/x509"
	"github.com/pkg/errors"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"io/ioutil"
	"net/http"
	gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime"
	"app/pb"
)

func NewGRpcConn(hostAndPort, caPath, clientCrt, clientKey string) (*grpc.ClientConn, error) {
	if caPath == "" {
		return grpc.Dial(hostAndPort, grpc.WithInsecure())
	}
	if caPath != "" && (clientCrt == "" || clientKey == "") {
		return nil, errors.Errorf("invalid credentials for:%v", hostAndPort)
	}
	cPool := x509.NewCertPool()
	caCert, err := ioutil.ReadFile(caPath)
	if err != nil {
		return nil, errors.Errorf("invalid CA crt file: %s", caPath)
	}
	if cPool.AppendCertsFromPEM(caCert) != true {
		return nil, errors.Errorf("failed to parse CA crt")
	}

	clientCert, err := tls.LoadX509KeyPair(clientCrt, clientKey)
	if err != nil {
		return nil, errors.Errorf("invalid client crt file: %s", caPath)
	}

	clientTLSConfig := &tls.Config{
		RootCAs:      cPool,
		Certificates: []tls.Certificate{clientCert},
	}
	creds := credentials.NewTLS(clientTLSConfig)

	conn, err := grpc.Dial(hostAndPort, grpc.WithTransportCredentials(creds))
	if err != nil {
		return nil, errors.Errorf("dial %v failed: %v", hostAndPort, err)
	}
	return conn, nil
}



// newGateway returns a new gateway server which translates HTTP into gRPC.
func NewGateway(ctx context.Context, conn *grpc.ClientConn, opts []gwruntime.ServeMuxOption) (http.Handler, error) {

	mux := gwruntime.NewServeMux(opts...)

	for _, f := range []func(context.Context, *gwruntime.ServeMux, *grpc.ClientConn) error{
		pb.RegisterUserServiceHandler,
	} {
		if err := f(ctx, mux, conn); err != nil {
			return nil, err
		}
	}
	return mux, nil
}
